#if WINDOWS_UWP
using OpenAI.ObjectModels.RequestModels;

public class ChatAgentService : ComRequestBaseClass
{
    //Dictionary of chatDict from different agents, keyed by Id
    private Dictionary<string, ChatAgent> _chatAgents = new();

    public event Action<ChatAgent, string, List<ToolCall>> OnAssistMsgAddedToAgent;

    public ChatAgentService(OpenAIComService openAIComService, HumanComService humanComService, ToolSetConfigBase toolSetConfig) 
        : base(openAIComService, humanComService, toolSetConfig)
    {
    }

    /// <summary>
    /// This service can only process agents that are authorized to move next
    /// </summary>
    public override void Update()
    {
        var chatAgents = _chatAgents.Values;
        var orderedAgents = chatAgents
                .Where(a => a.CanMoveNext && a.AuthorizedToMoveNext)
                .OrderBy(a => a.GetNextQueuedMsgReceivedTime());

        foreach (var chatAgent in orderedAgents)
        {
            var chatList = chatAgent.MoveNextChatIfQueued();
            if (chatList != null)
            {
                if (chatAgent.isHuman)
                {
                    UpdateHumanChatHistory(chatList[^1].Content);
                }
                else
                {
                    MakeChatAPIRequest(chatAgent.ID, chatAgent.gptModel, chatList, chatAgent.canFuncCall, $"{chatAgent.Name} ");
                }
            }
        }
    }

    protected override void OpenAiChatResponseHandler(string requesterId, string response, List<ToolCall> toolCalls)
    {
        if (_chatAgents.ContainsKey(requesterId) == false)
        {
            Debug.LogError($"Failed to find agent with Id {requesterId}");
            return;
        }

        var targetAgent = _chatAgents[requesterId];

        var authorName = ChatStringExtension.NameAsSystemReadable(targetAgent.Name);

        //APIComService.RequestTts(response, true);
        if (string.IsNullOrEmpty(response) == false && toolCalls == null) //just assistent msg
        {
            //this is only to add to chat's chat log
            targetAgent.AddChatRespond(response, authorName, null);
            targetAgent.RemoveAuthorization();

            OnAssistMsgAddedToAgent?.Invoke(_chatAgents[requesterId], response, null);
        }
        else if (toolCalls != null) //just tool call or Assistent + ToolCall
        {
            targetAgent.AddChatRespond(response, authorName, toolCalls);
            var toolCallResult = FunctionCallerService.ToolInvoker(toolCalls);
            //I won't trigger on assist msg added to agent yet, this would be triggered by the next time i got reply for this tool message from a assitent role OpenAiAPI reply. 
            targetAgent.AddChatRequest(toolCallResult, "ToolCall");
        }
        else //both msg and tool call is empty. 
        {
            //this is only to add to chat's chat log, this will not invoke OnAssistMsgAddedToAgent as no one wants to responsed on that. 
            targetAgent.AddChatRespond(response, authorName, null);
            targetAgent.RemoveAuthorization();
        }
    }

    protected override void HumanChatMsgHandler(string chatMsg)
    {
        var humanAgent = _chatAgents.Select(a => a.Value).First(a => a.agentEnum == ChatAgentEnum.Client);

        if (humanAgent == null)
        {
            Debug.LogError($"Human Agent Should always be in a chat room");
            return;
        }

        var authorName = ChatStringExtension.NameAsSystemReadable(humanAgent.Name);
        humanAgent.AddChatRespond(chatMsg, authorName, null);
        humanAgent.RemoveAuthorization();
        OnAssistMsgAddedToAgent?.Invoke(humanAgent, chatMsg, null);
    }

    /// <param name="agentSetupInfo"></param>
    /// <returns>agentId</returns>
    public ChatAgent CreateAgent(AgentSetupInfo agentSetupInfo)
    {
        var newAgent = new ChatAgent(agentSetupInfo);

        _chatAgents.Add(newAgent.ID, newAgent);
        return newAgent;
    }

    public void AddUserMsg(string agentId, string chatMessage, string author)
    {
        if (_chatAgents.ContainsKey(agentId) == false)
        {
            Debug.LogError($"Failed to find agent with Id: {agentId}");
            return;
        }

        _chatAgents[agentId].AddChatRequest(chatMessage, author);
    }

    public ChatAgent this[string agentId] => _chatAgents[agentId];

    public void ClearAgent(string agentId)
    {
        _chatAgents.Remove(agentId);
    }
}
#endif
